﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NPlot;

namespace TermEquation
{
  public partial class UIForm : Form
  {

    const int NPOINT = 1000;

    public UIForm()
    {
      InitializeComponent();
    }

    private void GetCoeffs(ITask task, int n, ref double[] a, ref double[] b, ref double[] c, ref double[] fi)
    {
      double h = 1.0 / (n + 1);
      a = new double[n];
      b = new double[n];
      c = new double[n];
      fi = new double[n];
      for (int i = 1; i <= n; i++)
      {
        double ai = task.a(i, h);
        double ai1 = task.a(i + 1, h);
        a[i - 1] = ai / (h * h);
        b[i - 1] = ai1 / (h * h);
        c[i - 1] = task.d(i, h) + ai / (h * h) + ai1 / (h * h);
        fi[i - 1] = task.fi(i, h);
      }
    }

    private void btnCalc_Click(object sender, EventArgs e)
    {
      label1.Text = "max|eps| = ";
      label2.Text = "ArgMax|eps| = ";
      dgvResult.Rows.Clear();
      plotSurface2D1.Clear();
      plotSurface2D2.Clear();
      int n = Convert.ToInt32(tbN.Text);
      double h = 1.0 / n;
      double mu1, mu2;
      double[] v2 = null;
      double[] arrEps = new double[n + 1];
              double maxEps = 0;
        int xi = 0;
      ITask task;
      if (rbMainTask.Checked)
      {
        task = new MainTask();
        mu1 = MainTask.mu1;
        mu2 = MainTask.mu2;
      }
      else
      {
        if (rbTestTask1.Checked)
        {
          task = new TestTask1();
          mu1 = TestTask1.mu1;
          mu2 = TestTask1.mu2;
        }
        else
        {
          task = new TestTask2();
          mu1 = TestTask2.mu1;
          mu2 = TestTask2.mu2;
        }
      }
      double[] a = null, b = null, c = null, fi = null;
      GetCoeffs(task, n - 1, ref a, ref b, ref c, ref fi);
      double[] x = new double[n + 1];
      for (int i = 0; i < n + 1; i++)
        x[i] = i * h;
      double k1 = 0, k2 = 0;
      DiagMethod solver = new DiagMethod(n + 1, a, b, c, fi, k1, k2, mu1, mu2);
      double[] v = solver.Solve();
      plotSurface2D1.Clear();
      plotSurface2D2.Clear();
      if (rbTestTask1.Checked)
      {
        double h1 = 1.0 / (NPOINT - 1);
        double[] u = new double[NPOINT];
        double[] x1 = new double[NPOINT];
        for (int i = 0; i < NPOINT; i++)
        {
          u[i] = (task as TestTask1).GetSolution(i * h1);
          x1[i] = i * h1;
        }
        LinePlot lp = new LinePlot();
        lp.OrdinateData = u;
        lp.AbscissaData = x1;
        lp.Pen = new Pen(Color.Red, 1.0f);
        plotSurface2D1.Add(lp);
        this.plotSurface2D1.Refresh();
        LinePlot lp1 = new LinePlot();
        lp1.OrdinateData = v;
        lp1.AbscissaData = x;
        lp1.Pen = new Pen(Color.Black, 1.0f);
        plotSurface2D1.Add(lp1);
        this.plotSurface2D1.Refresh();
      }
      if (rbTestTask2.Checked)
      {
        double h1 = 1.0 / (NPOINT - 1);
        double[] u = new double[NPOINT];
        double[] x1 = new double[NPOINT];
        for (int i = 0; i < NPOINT; i++)
        {
          u[i] = (task as TestTask2).GetSolution(i * h1);
          x1[i] = i * h1;
        }
        LinePlot lp = new LinePlot();
        lp.OrdinateData = u;
        lp.AbscissaData = x1;
        lp.Pen = new Pen(Color.Red, 1.0f);
        plotSurface2D1.Add(lp);
        this.plotSurface2D1.Refresh();
        LinePlot lp1 = new LinePlot();
        lp1.OrdinateData = v;
        lp1.AbscissaData = x;
        lp1.Pen = new Pen(Color.Black, 1.0f);
        plotSurface2D1.Add(lp1);
        this.plotSurface2D1.Refresh();
      }
      //output coeficeints
      if (rbMainTask.Checked)
      {
        //solve for another net
        double h2 = 1.0 / (2 * n);
        double[] a2 = null, b2 = null, c2 = null, fi2 = null;
        GetCoeffs(task, 2 * n - 1, ref a2, ref b2, ref c2, ref fi2);
        DiagMethod solver2 = new DiagMethod(2 * n + 1, a2, b2, c2, fi2, k1, k2, mu1, mu2);
        v2 = solver2.Solve();
        double[] x2 = new double[2 * n + 1];
        for (int i = 0; i <= 2 * n; i++)
          x2[i] = i * h2;
        LinePlot lp2 = new LinePlot();
        lp2.OrdinateData = v2;
        lp2.AbscissaData = x2;
        lp2.Pen = new Pen(Color.Red, 1.0f);
        plotSurface2D1.Add(lp2);
        this.plotSurface2D1.Refresh();
        LinePlot lp1 = new LinePlot();
        lp1.OrdinateData = v;
        lp1.AbscissaData = x;
        lp1.Pen = new Pen(Color.Black, 1.0f);
        plotSurface2D1.Add(lp1);
        this.plotSurface2D1.Refresh();
      }
      // Вычислить Eps
      for (int i = 0; i < n - 1; i++)
      {
        double eps = 0;
        if (rbTestTask1.Checked)
          eps = (task as TestTask1).GetSolution((i + 1) * h) - v[i + 1];
        if (rbTestTask2.Checked)
          eps = (task as TestTask2).GetSolution((i + 1) * h) - v[i + 1];
        if (rbMainTask.Checked)
        {
          eps = v[i + 1] - v2[2 * (i + 1)];
        }
        arrEps[i + 1] = eps;
        if (Math.Abs(eps) > maxEps)
        {
          maxEps = Math.Abs(eps);
          xi = i;
        }
      }
      // Вывод графика Eps
      if (checkBox1.Checked)
      {
        LinePlot lp2 = new LinePlot();
        lp2.OrdinateData = arrEps;
        lp2.AbscissaData = x;
        lp2.Pen = new Pen(Color.Blue, 1.0f);
        plotSurface2D2.Add(lp2);
        this.plotSurface2D2.Refresh();
      }
      // Вывод eps на экран 
      label1.Text += maxEps.ToString("E2");
      label2.Text += (xi*h).ToString("G4");
        // Показать коэффициенты
      if (cbShowResult.Checked)
      {
        lblEpsName.Text = "max|eps|";
        for (int i = 0; i < n - 1; i++)
        {
          dgvResult.Rows.Add();
          dgvResult.Rows[i].Cells[0].Value = Convert.ToString((i + 1) * h);
          dgvResult.Rows[i].Cells[1].Value = task.a(i + 1, h).ToString("G5");
          dgvResult.Rows[i].Cells[2].Value = task.fi(i + 1, h).ToString("G5");
          dgvResult.Rows[i].Cells[3].Value = task.d(i + 1, h).ToString("G5");
          dgvResult.Rows[i].Cells[4].Value = v[i + 1].ToString("G5");
          dgvResult.Rows[i].Cells[5].Value = arrEps[i + 1];
        }
      }
    }
  }
}